import {
  _decorator,
  AudioClip,
  Component,
  Input,
  Sprite,
  SpriteAtlas,
  UITransform,
} from 'cc'
import { GAME_BOARD_ENUM, GAME_EVENT_ENUM, GAME_STATUS_ENUM } from '../Enum'
import { BlockType } from '../type'
import { CHANGE_BOARD, CHECK_CLEAR } from '../Event'
import { DataManager } from '../DataManager'
import { AudioMgr } from '../AudioMgr'
const { ccclass, property } = _decorator

@ccclass('Block')
export class Block extends Component implements BlockType {
  id: number
  x: number
  y: number
  width: number
  height: number
  layer: number
  private _boardType: GAME_BOARD_ENUM // 在游戏面板中的类型
  type: number // 块类型
  coverIds: number[] // 覆盖块的块id
  beCoverIds: number[] // 被覆盖的块id
  @property(SpriteAtlas)
  spriteAtlas: SpriteAtlas = null
  @property({ type: AudioClip })
  clickBlock: AudioClip = null
  // 初始化原始数据
  old_boardType: GAME_BOARD_ENUM = null
  old_x: number = null
  old_y: number = null
  old_width: number = null
  old_height: number = null
  old_layer: number = null
  get boardType(): GAME_BOARD_ENUM {
    return this._boardType
  }
  set boardType(value: GAME_BOARD_ENUM) {
    if (this._boardType !== value) {
      this._boardType = value
      CHANGE_BOARD.emit(GAME_EVENT_ENUM.CHANGE_BOARD, this)
    }
  }
  protected onLoad(): void {
    this.node.on(Input.EventType.TOUCH_START, this.onTouchStart, this)
  }
  protected onDestroy(): void {
    this.node.off(Input.EventType.TOUCH_START, this.onTouchStart, this)
  }
  // 初始化
  init(block: BlockType) {
    // 将block属性合并到当前对象
    Object.assign(this, block)
    // 将块放在DataManager中
    DataManager.inst.blocks.push(this)
    this.old_boardType = block.boardType
    this.old_x = block.x
    this.old_y = block.y
    this.old_width = block.width
    this.old_height = block.height
    this.old_layer = block.layer
    this.render()
  }
  // 块渲染，更新位置，优先级，背景遮罩
  render() {
    this.node.setPosition(this.x, this.y)
    this.node.getComponent(UITransform).width = this.width
    this.node.getComponent(UITransform).height = this.height
    this.node.getComponent(UITransform).priority = this.layer
    this.node.setSiblingIndex(this.layer)
    this.node.getComponent(Sprite).spriteFrame =
      this.spriteAtlas.getSpriteFrames()[this.type]
    // 设置是否有遮罩层
    if (this.boardType === GAME_BOARD_ENUM.SLOT) {
      this.node.getChildByName('bg').active = false
    } else {
      this.node.getChildByName('bg').active = !this.clickable()
    }
  }
  // 检查是否可点击
  clickable(): boolean {
    // 使用技能‘明牌’，全部可点击
    if (DataManager.inst.clickable) return true
    switch (this.boardType) {
      // 在主面板，左随机区，右随机区且无被覆盖的块可点击
      case GAME_BOARD_ENUM.LEVEL:
      case GAME_BOARD_ENUM.RANDOM_LEFT:
      case GAME_BOARD_ENUM.RANDOM_RIGHT:
        return this.beCoverIds.length <= 0
      // 扩展区可点击
      case GAME_BOARD_ENUM.LEVEL_EXTEND:
        return true
    }
  }
  // 点击后入槽
  toSlot() {
    // 如果当前记录槽中无块，则添加
    if (!DataManager.inst.records.find(item => item.id === this.id)) {
      DataManager.inst.records.push(this)
    }
    this.layer = 0
    this.y = 0 // 相对于槽中位置为0
    this.boardType = GAME_BOARD_ENUM.SLOT
    // 获取槽中所有数据
    const slotsAll = DataManager.inst.blocks.filter(
      item => item.boardType === GAME_BOARD_ENUM.SLOT,
    )
    // 获取相同的槽
    const slotsSame = slotsAll.filter(item => item.type === this.type)
    // 将相同的槽放置在最后
    let maxLayer = 0
    slotsAll.forEach(block => {
      if (block.layer > maxLayer) {
        maxLayer = block.layer
      }
    })
    slotsSame.forEach(block => {
      block.layer = maxLayer + 1
      block.render()
    })

    // 执行消除操作
    CHECK_CLEAR.emit(GAME_EVENT_ENUM.CHECK_CLEAR, this)

    // 计算覆盖块
    this.coverIds.forEach(id => {
      const block: Block = DataManager.inst.blocks.find(item => item.id === id)
      if (block.beCoverIds.find(item => item === this.id) >= 0) {
        block.beCoverIds.splice(block.beCoverIds.indexOf(this.id), 1)
      }
      block.render()
    })
  }
  // 出槽
  toSlotCancel() {
    // todo
  }
  onTouchStart() {
    // 在槽中，不响应点击事件
    if (this.boardType === GAME_BOARD_ENUM.SLOT) return
    // 游戏不为运行中，不响应点击事件
    if (DataManager.inst.gameStatus !== GAME_STATUS_ENUM.RUNNING) return
    // 无法点击，不响应点击事件
    if (!this.clickable()) return
    // 点击音效
    AudioMgr.inst.playOneShot(this.clickBlock, 1)
    // 点击动画效果
    // 入槽
    this.toSlot()
  }
}
